﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Services;
using System.Data.Objects;
using System.Data;
using ADONETDataServicesExtension;
using ADONETDataServicesExtension.BLLUtils;
using EFEntities;

namespace BLL
{
    public class Context : BaseContext<ADONETDataServicesHookingPOCEntities>
    {
        public IQueryable<T> ConvertIntoObjects<T, K>(ObjectQuery<K> efQuery, Func<K, T> newT)
        {
            return ConvertIntoObjects(efQuery.AsEnumerable(), newT);
        }

        public IQueryable<T> ConvertIntoObjects<T, K>(IEnumerable<K> enumerableQuery, Func<K, T> newT)
        {
            return enumerableQuery.Select(newT).AsQueryable();
        }

        private ObjectQuery<EFEntities.Employee> EFEmployeesInActivity
        {
            get
            {
                return EFContext.Employees;
            }
        }

        private ObjectQuery<EFEntities.Employee> EFEmployees
        {
            get
            {
                return EFEmployeesInActivity;
            }
        }
        public IQueryable<Employee> Employees
        {
            get
            {
                return ConvertIntoObjects(EFEmployees, e => new Employee(e));
            }
        }

        private ObjectQuery<EFEntities.Employee> EFManagers
        {
            get
            {
                return EFEmployeesInActivity.Where(Employee.IsManagerExpression()) as ObjectQuery<EFEntities.Employee>;
            }
        }
        public IQueryable<Manager> Managers
        {
            get
            {
                return ConvertIntoObjects(EFManagers, m => new Manager(m));
            }
        }

        private ObjectQuery<EFEntities.Role> EFRoles
        {
            get
            {
                return EFContext.Roles;
            }
        }
        public IQueryable<Role> Roles
        {
            get
            {
                return ConvertIntoObjects(EFRoles, r => new Role(r));
            }
        }

        private ObjectQuery<EFEntities.Team> EFTeams
        {
            get
            {
                return EFContext.Teams;
            }
        }
        public IQueryable<Team> Teams
        {
            get
            {
                return ConvertIntoObjects(EFTeams, t => new Team(t));
            }
        }

        private ObjectQuery<EFEntities.Employee> EFTeamManagers
        {
            get
            {
                return EFEmployeesInActivity.Where(Employee.IsTeamManagerExpression()) as ObjectQuery<EFEntities.Employee>;
            }
        }
        public IQueryable<TeamManager> TeamManagers
        {
            get
            {
                return ConvertIntoObjects(EFTeamManagers, tm => new TeamManager(tm));
            }
        }

        private IEnumerable<T> GetTElements<T>(ObjectQuery query)
        {
            foreach (object o in query)
                yield return (T)o;
        }
        protected override IQueryable EncapsulateIntoBLLEntityType(ObjectQuery efQuery, Type type, string login)
        {
            if (type == typeof(Employee))
                return ConvertIntoObjects<Employee, EFEntities.Employee>(GetTElements<EFEntities.Employee>(efQuery), e => new Employee(e) { Login = login });
            if (type == typeof(Manager))
                return ConvertIntoObjects<Manager, EFEntities.Employee>(GetTElements<EFEntities.Employee>(efQuery), e => new Manager(e) { Login = login });
            if (type == typeof(Role))
                return ConvertIntoObjects<Role, EFEntities.Role>(GetTElements<EFEntities.Role>(efQuery), r => new Role(r) { Login = login });
            if (type == typeof(Team))
                return ConvertIntoObjects<Team, EFEntities.Team>(GetTElements<EFEntities.Team>(efQuery), t => new Team(t) { Login = login });
            if (type == typeof(TeamManager))
                return ConvertIntoObjects<TeamManager, EFEntities.Employee>(GetTElements<EFEntities.Employee>(efQuery), e => new TeamManager(e) { Login = login });
            throw new NotImplementedException();
        }

        protected override ObjectQuery GetEFQuery(string propertyName)
        {
            switch (propertyName)
            {
                case "Employees":
                    return EFEmployees;
                case "Managers":
                    return EFManagers;
                case "Roles":
                    return EFRoles;
                case "Teams":
                    return EFTeams;
                case "TeamManagers":
                    return EFTeamManagers;
            }
            throw new NotImplementedException();
        }
    }
}
